package com.wave.lib;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListAdapter;
import android.widget.ListView;

import com.handmark.pulltorefresh.library.R;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;

/**
 * SwipeListView.java
 *
 * @author Wave.Zhang
 * @data 2015-5-13 t下午2:43:22
 */
public class SwipeListView extends ListView {

    private static final int TOUCH_STATE_NONE = 0;
    private static final int TOUCH_STATE_X = 1;
    private static final int TOUCH_STATE_Y = 2;
    private static boolean firstItemSwipe = true;
    /**
     * Default ids for front view
     */
    public final static String SWIPE_DEFAULT_FRONT_VIEW = "swipelist_frontview";


    public final static String SWIPE_DEFAULT_RIGHT_VIEW = "swipelist_rightview";

    public final static String SWIPE_DEFAULT_LEFT_VIEW = "swipelist_leftview";

    private int MAX_Y = 5;
    private int MAX_X = 3;

    private float mDownX;
    private float mDownY;

    private int mTouchState;
    private int mTouchPosition;

    //private SimpleOnGestureListener mGestureListener;
    //private GestureDetectorCompat mGestureDetector;

    private int MIN_FLING = dp2px(15);
    private int MAX_VELOCITYX = -dp2px(500);

    private boolean isFling;


    private int swipeMode = 0;

    public SwipeListView(Context context) {
        super(context);
        init(context, null);
    }

    public SwipeListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // wave-zhang
        init(context, attrs);
    }

    public SwipeListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        MAX_X = dp2px(MAX_X);
        MAX_Y = dp2px(MAX_Y);
        mTouchState = TOUCH_STATE_NONE;

        if (attrs != null) {
            TypedArray styled = getContext().obtainStyledAttributes(attrs, R.styleable.SwipeListView);
            swipeFrontViewId = styled.getResourceId(R.styleable.SwipeListView_swipeFrontView, 0);
            swipeRightViewId = styled.getResourceId(R.styleable.SwipeListView_swipeRightView, 0);
            swipeLeftViewId = styled.getResourceId(R.styleable.SwipeListView_swipeLeftView, 0);
            swipeMode = styled.getInt(R.styleable.SwipeListView_swipeMode, 0);
        }
        if (swipeFrontViewId == 0) {
            swipeFrontViewId = getContext().getResources().getIdentifier(SWIPE_DEFAULT_FRONT_VIEW, "id", getContext().getPackageName());
            swipeRightViewId = getContext().getResources().getIdentifier(SWIPE_DEFAULT_RIGHT_VIEW, "id", getContext().getPackageName());
            swipeLeftViewId = getContext().getResources().getIdentifier(SWIPE_DEFAULT_LEFT_VIEW, "id", getContext().getPackageName());

            if (swipeFrontViewId == 0 || swipeRightViewId == 0) {
                throw new RuntimeException(String.format("You forgot the attributes swipeFrontView or swipeBackView or swipeRightView. You can add this attributes or use '%s' and '%s' identifiers", SWIPE_DEFAULT_FRONT_VIEW, SWIPE_DEFAULT_RIGHT_VIEW));
            }
        }

//	    mGestureListener = new SimpleOnGestureListener() {
//			@Override
//			public boolean onDown(MotionEvent e) {
//				isFling = false;
//				return true;
//			}
//
//			@Override
//			public boolean onFling(MotionEvent e1, MotionEvent e2,
//					float velocityX, float velocityY) {
//				// TODO
//				if ((e1.getX() - e2.getX()) > MIN_FLING && velocityX < MAX_VELOCITYX) {
//					isFling = true;
//				}
//				// Log.i("byz", MAX_VELOCITYX + ", velocityX = " + velocityX);
//				return super.onFling(e1, e2, velocityX, velocityY);
//			}
//		};
//
//		mGestureDetector = new GestureDetectorCompat(getContext(),mGestureListener);
    }

    @Override
    public void setAdapter(ListAdapter adapter) {
        super.setAdapter(adapter);
    }

    private View mView;

    private int swipeFrontViewId;

    private int swipeRightViewId;

    private int swipeLeftViewId;

    private View mContentView;

    private View mMenuView;

    private View mLeftMenuView;

    private static final String tag = "wave";

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() != MotionEvent.ACTION_DOWN && mView == null)
            return super.onTouchEvent(ev);
        int action = MotionEventCompat.getActionMasked(ev);
        action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                int oldPos = mTouchPosition;
                mDownX = ev.getX();
                mDownY = ev.getY();
                mTouchState = TOUCH_STATE_NONE;

                mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
                Log.e(tag, "::::::" + mTouchPosition);

                //判断手指起来的时候晃动 +-20的距离都算点击
                if (onCloseSwipeItemClickListener != null) {
                    onCloseSwipeItemClickListener.onItemClick(mTouchPosition, isOpenMenu());
                }
                if (mTouchPosition == oldPos && mView != null && isOpen()) {
                    mTouchState = TOUCH_STATE_X;
                    onSwipeing(ev);
                    Log.d(tag, "down oldPos && isOpen return true");
                    return true;
                }
                Log.d(tag, "down mView != null " + (mView == null ? " null " : " not null") + " && isOpen return " + isOpenMenu());
                if (mView != null && isOpenMenu()) {
                    mView = null;
                    closeMenuView();
                    MotionEvent cancelEvent = MotionEvent.obtain(ev);
                    cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
                    onTouchEvent(cancelEvent);
                    return true;
                }

                mView = getChildAt(mTouchPosition - getFirstVisiblePosition());

                if (mView != null && swipeFrontViewId > 0) {
                    mContentView = mView.findViewById(swipeFrontViewId);
                }

                if (mView != null && swipeRightViewId > 0) {
                    mMenuView = mView.findViewById(swipeRightViewId);
                }

                if (mView != null && swipeLeftViewId > 0) {
                    mLeftMenuView = mView.findViewById(swipeLeftViewId);
                }

                Log.d(tag, "down swipeLeftViewId = " + swipeLeftViewId + " swipeLeftViewId = " + swipeLeftViewId + "  / mLeftMenuView == " + (mLeftMenuView == null ? " is null " : "is not null"));
                Log.d(tag, "down swipeRightViewId = " + swipeRightViewId + " swipeRightViewId = " + swipeRightViewId + "  / mView == " + (mView == null ? " is null " : "is not null"));
                Log.d(tag, "down mContentView = " + (mContentView == null ? "is null" : " is not null,") + " mMenuView = " + (mMenuView == null ? "is null" : " is not null,"));

                if (mView != null && mContentView != null) {
                    Log.d(tag, "onSwipe = ");
                    onSwipeing(ev);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (callback != null)
                    callback.callback(mTouchPosition, isOpenMenu());
                if (isAutoSwipeItem)
                    break;
//			boolean bool = getGesture(mDownX,mDownY,ev);
//			if(bool) break;
                float dy = Math.abs((ev.getY() - mDownY));
                float dx = Math.abs((ev.getX() - mDownX));
                if (mTouchState == TOUCH_STATE_X) {
                    if (mView != null) {
                        onSwipeing(ev);
                    }
                    getSelector().setState(new int[]{0});
                    ev.setAction(MotionEvent.ACTION_CANCEL);
                    super.onTouchEvent(ev);
                    return true;
                } else if (mTouchState == TOUCH_STATE_NONE) {
                    if (Math.abs(dy) > MAX_Y) {
                        mTouchState = TOUCH_STATE_Y;
                    } else if (dx > MAX_X) {
                        mTouchState = TOUCH_STATE_X;
//					if (mOnSwipeListener != null) {
//						mOnSwipeListener.onSwipeStart(mTouchPosition);
//					}
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                //判断手指起来的时候晃动 +-20的距离都算点击
                if (onItemClickListener != null && mDownY < ev.getY() + 20 && mDownY > ev.getY() - 20)
                    onItemClickListener.onItemClick(mTouchPosition, isOpenMenu());
                if (mTouchState == TOUCH_STATE_X) {
                    if (mView != null) {
                        onSwipeing(ev);
                        if (!isOpen()) {
                            mTouchPosition = -1;
                            mView = null;
                        }
                    }
                    ev.setAction(MotionEvent.ACTION_CANCEL);
                    super.onTouchEvent(ev);
                    return true;
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                getContext().getResources().getDisplayMetrics());
    }

    int mSwipeDownX = 0;

    public boolean onSwipeing(MotionEvent event) {
        if (!firstItemSwipe && mTouchPosition == 0) {
            return true;
        }
        //mGestureDetector.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mSwipeDownX = (int) event.getX();
                isFling = false;
                Log.d(tag, "ACTION_DOWN oldPos && isOpen return true  onSwipe --- mSwipeDownX " + mSwipeDownX);
                break;
            case MotionEvent.ACTION_MOVE:
                // Log.i("byz", "downX = " + mDownX + ", moveX = " + event.getX());
                // int dis = (int) (mDownX - event.getX());
                stateTag = 2;
                //move(dis);
                Log.d(tag, "ACTION_MOVE --- mSwipeDownX " + mSwipeDownX);

                float deltaX = event.getRawX() - mSwipeDownX;
                move(deltaX);

                break;
            case MotionEvent.ACTION_UP:
                if (swipeMode > 0) {
                    if (swipeMode > 0 && event.getX() - mSwipeDownX > (mLeftMenuView.getWidth() / 2)) {
                        openMenuView();
                    } else {
                        closeMenuView();
                    }
                } else {
                    if (swipeMode <= 0 && (mSwipeDownX - event.getX()) > (mMenuView.getWidth() / 2)) {
                        openMenuView();
                    } else {
                        closeMenuView();
                    }
                }

                Log.d(tag, "ACTION_UP --- mDownX " + mSwipeDownX);
                break;
        }
        return true;
    }

    int stateTag = 0;

    public boolean isOpen() {
        return stateTag == 1;
    }

    private void move(float deltaX) {
        stateTag = 2;
        //setTranslationX(fontViewId, ()dis);
//		if (dis > mMenuView.getWidth()) {
//			dis = mMenuView.getWidth();
//		}
//		if (dis < 0) {
//			dis = 0;
//		}
//		mContentView.layout(-dis, mContentView.getTop(),mContentView.getWidth() - dis, getMeasuredHeight());
//		mMenuView.layout(mContentView.getWidth() - dis, mMenuView.getTop(),mContentView.getWidth() + mMenuView.getWidth() - dis,mMenuView.getBottom());
        //isFling =  true;
        //float deltaMode = Math.abs(deltaX);
        Log.d(tag, "deltaX ---->" + deltaX);
        if (swipeMode > 0) {
            if (deltaX > (mLeftMenuView.getWidth())) {
                deltaX = mLeftMenuView.getWidth();
            }
            // 禁止左滑
            if (deltaX < 0) deltaX = 0;
        } else {
            if (deltaX <= (-mMenuView.getWidth())) {
                deltaX = -mMenuView.getWidth();
            }
            // 禁止左滑
            if (deltaX > 0) deltaX = 0;
        }
        com.nineoldandroids.view.ViewHelper.setTranslationX(mContentView, deltaX);
        com.nineoldandroids.view.ViewHelper.setTranslationX(swipeMode > 0 ? mLeftMenuView : mMenuView, deltaX);
    }

    public void closeMenuView() {
        if (swipeMode > 0) {
            if (mContentView != null) closeAnimate(mContentView, 0, null);
            if (mMenuView != null) closeAnimate(mLeftMenuView, 0, null);
        } else {
            if (mContentView != null) closeAnimate(mContentView, 0, null);
            if (mMenuView != null) closeAnimate(mMenuView, 0, null);
        }
    }

    ;

    public interface OnCloseMenuEndListener {

        void onEndAction(View v);
    }

    public void closeMenuView(OnCloseMenuEndListener menuEndListener) {
        if (swipeMode > 0) {
            if (mContentView != null) closeAnimate(mContentView, 0, null);
            if (mMenuView != null) closeAnimate(mLeftMenuView, 0, menuEndListener);
        } else {
            if (mContentView != null) closeAnimate(mContentView, 0, null);
            if (mMenuView != null) closeAnimate(mMenuView, 0, menuEndListener);
        }


    }

    ;

    public void openMenuView() {
        stateTag = 1;
        if (swipeMode > 0) {
            if (mContentView != null && mLeftMenuView != null)
                openItemAnimate(mContentView, 0, mLeftMenuView.getWidth());
            if (mContentView != null && mLeftMenuView != null)
                openItemAnimate(mLeftMenuView, 0, mLeftMenuView.getWidth());
        } else {
            if (mContentView != null && mMenuView != null)
                openItemAnimate(mContentView, 0, -mMenuView.getWidth());
            if (mContentView != null && mMenuView != null)
                openItemAnimate(mMenuView, 0, -mMenuView.getWidth());
        }
    }

    public boolean isOpenMenu() {
        return ((stateTag == 1 || stateTag == 2) ? true : false);
    }

    void resetCell() {
        stateTag = 0;
        mView = null;
    }

    /**
     * Create choice animation
     *
     * @param view     affected view
     * @param position list position
     */
    public void closeAnimate(final View view, final int position, final OnCloseMenuEndListener mCloseMenuEndListener) {
        com.nineoldandroids.view.ViewPropertyAnimator.animate(view).translationX(0).alphaBy(0)
                .setDuration(200)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        //swipeListView.resetScrolling();
                        resetCell();
                        if (mCloseMenuEndListener != null) mCloseMenuEndListener.onEndAction(view);
                    }
                });
    }

    public void openItemAnimate(final View view, final int position, float mX) {
        com.nineoldandroids.view.ViewPropertyAnimator.animate(view).translationX(mX)
                .setDuration(200)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        // swipeListView.resetScrolling();
                        // resetCell();
                    }
                });
    }

    public interface OnItemClickListener {
        /**
         * @param position   点击位置
         * @param isOpenMenu menu 开关状态
         */
        void onItemClick(int position, boolean isOpenMenu);
    }

    private OnItemClickListener onItemClickListener;

    /**
     * item click
     *
     * @param onItemClickListener
     */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }


    public interface OnCloseSwipeItemClickListener {
        /**
         * @param position   点击位置
         * @param isOpenMenu menu 开关状态
         */
        void onItemClick(int position, boolean isOpenMenu);
    }

    public interface OnCallBack {
        /**
         * @param position   点击位置
         * @param isOpenMenu menu 开关状态
         */
        void callback(int position, boolean isOpenMenu);
    }

    private OnCallBack callback;

    private OnCloseSwipeItemClickListener onCloseSwipeItemClickListener;
    private boolean isAutoSwipeItem = false;

    public void setAutoSwipeItem(boolean b, OnCallBack callback) {
        isAutoSwipeItem = b;
        this.callback = callback;
    }

    /**
     * item click
     *
     * @param onCloseSwipeItemClickListener
     */
    public void setOnCloseSwipeItemClickListener(OnCloseSwipeItemClickListener onCloseSwipeItemClickListener) {
        this.onCloseSwipeItemClickListener = onCloseSwipeItemClickListener;
    }

    /**
     * 设置第一行是否允许滑动
     *
     * @param bool
     */
    public void setFirstItemSwipe(boolean bool) {
        firstItemSwipe = bool;
    }

    public boolean getGesture(float mLastXIntercept, float mLastYIntercept, MotionEvent ev) {
        float tan = 0;//tan 角度
        if (ev.getX() < mLastXIntercept && ev.getY() < mLastYIntercept) {//在左上
            float tY = mLastYIntercept - ev.getY();
            float tX = mLastXIntercept - ev.getX();
            tan = tY / tX;
        } else if (ev.getX() > mLastXIntercept && ev.getY() < mLastYIntercept) {//在右上
            float tY = mLastYIntercept - ev.getY();
            float tX = ev.getX() - mLastXIntercept;
            tan = tY / tX;//小于这个角度则是左右滑动
        }
//                        Log.e("", "]]]]]]zzz" + rec[1] + "  " + isNotScrollViewPosition+"  "+tan+"  "+Math.sin(Math.toRadians(30)));
        if (tan < 0.6) {//左右滑动所有与坐标原点的角度
//			mLv.getRefreshableView().smoothScrollBy(0,0);
            return true;
        }
        return false;
    }
}
